package com.feixiang.springbootinit.aop;

import cn.hutool.core.date.DateUtil;
import com.feixiang.springbootinit.annotation.MonitorTask;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

@Slf4j
@Aspect
@Component
public class TaskMonitorAspect {

    // 使用ThreadLocal存储每个任务的开始时间（确保线程安全）
    private final ThreadLocal<Long> taskStartTime = new ThreadLocal<>();

    @Before("@annotation(com.feixiang.springbootinit.annotation.MonitorTask)")
    public void beforeTaskExecution(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        MonitorTask monitorTask = method.getAnnotation(MonitorTask.class);
        String taskName = monitorTask.value().isEmpty() ? method.getName() : monitorTask.value();

        // 记录任务开始时间
        long startTime = System.currentTimeMillis();
        taskStartTime.set(startTime);

        log.info("任务[{}]开始执行，时间: {}", taskName, DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
    }

    @AfterReturning("@annotation(com.feixiang.springbootinit.annotation.MonitorTask)")
    public void afterTaskSuccess(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        MonitorTask monitorTask = method.getAnnotation(MonitorTask.class);
        String taskName = monitorTask.value().isEmpty() ? method.getName() : monitorTask.value();

        // 计算任务耗时
        long endTime = System.currentTimeMillis();
        long duration = endTime - taskStartTime.get();
        taskStartTime.remove(); // 避免内存泄漏

        log.info("任务[{}]成功完成，时间: {}, 耗时: {}ms", taskName, DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), duration);

        // 记录方法参数
        Object[] args = joinPoint.getArgs();
        if (args != null && args.length > 0) {
            log.info("任务[{}]参数: {}", taskName, args);
        }
    }

    @AfterThrowing(pointcut = "@annotation(com.feixiang.springbootinit.annotation.MonitorTask)", throwing = "ex")
    public void afterTaskFailure(JoinPoint joinPoint, Throwable ex) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        MonitorTask monitorTask = method.getAnnotation(MonitorTask.class);
        String taskName = monitorTask.value().isEmpty() ? method.getName() : monitorTask.value();

        // 计算任务耗时（即使失败也记录耗时）
        long endTime = System.currentTimeMillis();
        long duration = endTime - taskStartTime.get();
        taskStartTime.remove(); // 避免内存泄漏
        log.info("任务[{}]执行失败，时间: {}, 耗时: {}ms, 异常: {}", taskName, DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), duration, ex.getMessage());
        log.error("任务[{}]执行失败，异常: {}", taskName, ex);
    }
}